/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.oimwrapper.testers;

import Thor.API.Operations.*;
import Thor.API.tcResultSet;
import com.thortech.util.logging.Logger;
import java.util.*;
import org.junit.Test;
import org.oimwrapper.connectors.OIMAdapterBase;
import org.oimwrapper.connectors.OIMRemoteClientBase;
import org.oimwrapper.connectors.internal.OIMObjectFormUtilities;
import org.oimwrapper.connectors.internal.OIMUtilityGetter;

/**
 *
 */
public class ClientObjectFormTester extends ClientBaseTester {
    
    private static final Logger logger = Logger.getLogger(ClientObjectFormTester.class.getName());
    
    private OIMRemoteClientBase client = null;
    private OIMAdapterBase apiBase = null;
    
    private String resourceName = "Resource B";
    private String objectInstanceKey = "3841";
    
    private tcFormInstanceOperationsIntf formInstOps;
    private tcFormDefinitionOperationsIntf formDefOps;
    private tcObjectOperationsIntf objectOp;
    private OIMObjectFormUtilities objFormUtils;
    
    
    @Test
    public void mainTest()
    {
        try
        {
            client = this.connect();
            apiBase = client.getUtils();
            formInstOps = (tcFormInstanceOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormInstanceOperationsIntf.class);
            formDefOps = (tcFormDefinitionOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormDefinitionOperationsIntf.class);
            objectOp = (tcObjectOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcObjectOperationsIntf.class);
            objFormUtils = OIMUtilityGetter.getObjectFormUtilities(logger, objectOp,formInstOps, formDefOps);
            
        }
        catch(Exception e)
        {
            logger.error("Connection Failed",e);
            return;
        }
        /*
        try
        {
            setNextGroupApprover(resourceName,objectInstanceKey);
        }
        catch(Exception e)
        {
            logger.error("Error getting ops");
            return;
        }
        * 
        */
        
        //getResourceFormInfo("Resource B");
        showChildren();
        
    }
    
    public void showChildren()
    {
        try
        {
            tcResultSet childFormDefs = formInstOps.getChildFormDefinition(42L, 1);
            printResultSet(childFormDefs);
        }
        catch(Exception e)
        {
            logger.error("APIError",e);
        }
                
    }
    
    public Map<String,List<Map>> getObjectChildFormFieldInfo(long formDefKey, int formVersion)
    {
        
        Map<String,List<Map>> childFormInfoMap = new HashMap<String,List<Map>>();
        
        try {
            tcResultSet childFormDefs = formInstOps.getChildFormDefinition(formDefKey, formVersion);
            printResultSet(childFormDefs);
            
            for(int i=0;i<childFormDefs.getRowCount();i++)
            {
                childFormDefs.goToRow(i);
                String tableName = childFormDefs.getStringValue("Structure Utility.Table Name");
                int childVersion = childFormDefs.getIntValue("Structure Utility.Child Tables.Child Version");
                long childDefKey = childFormDefs.getLongValue("Structure Utility.Child Tables.Child Key");
                tcResultSet fields = formDefOps.getFormFields(childDefKey, childVersion);
                
                String[] colNames = null;
                List fieldList = null;
                if (fields.getRowCount() > 0)
                {
                    colNames = fields.getColumnNames();
                    fieldList = new ArrayList();
                }
                for(int f=0;f<fields.getRowCount();f++)
                {
                    
                    fields.goToRow(f);
                    Map record = new HashMap();
                    for(String col : colNames)
                    {
                        String k = col;
                        String v = fields.getStringValue(k);
                        record.put(k,v);
                    }
                    fieldList.add(record);
                }
                childFormInfoMap.put(tableName,fieldList);
                printResultSet(fields);
            }
        } 
        catch (Exception e) 
        {
            logger.error("APIError",e);
        }
        return childFormInfoMap;
        
    }
    
    private void getResourceFormInfo(String resourceName)
    {
        Map provision = null;
        Map approval = null;
        
        try
        {
            Map[] resourceInfo = this.apiBase.getResourceFormInfo(resourceName);
            for(int m=0;m<resourceInfo.length;m++)
            {
                Map ri = resourceInfo[m];
                String type = (String)ri.get("Process Definition.Type");
                if (type.equalsIgnoreCase("Provisioning"))
                    provision = ri;
                if (type.equalsIgnoreCase("Approval"))
                    approval = ri;
                logger.debug("RI:" + ri);
            }
            
            List<Map> fieldInfo = null;
            
            if (approval != null)
            {
                logger.debug("Get Object Fields");
                String defKey = (String)approval.get("FORMDEFKEY");
                String ver = (String)approval.get("FORMVER");
                fieldInfo = this.objFormUtils.getObjectFormFieldInfo(Long.parseLong(defKey), Integer.parseInt(ver));
                Map<String,List<Map>> childTableFieldInfo = objFormUtils.getObjectChildFormFieldInfo(Long.parseLong(defKey), Integer.parseInt(ver));
                logger.debug("Parent");
                logger.debug("" + fieldInfo);
                logger.debug("Children");
                logger.debug("" + childTableFieldInfo);
                return;
            }
            if (provision != null)
            {
                logger.debug("Get Provision Fields");
                String defKey = (String)provision.get("FORMDEFKEY");
                String ver = (String)provision.get("FORMVER");
                fieldInfo = this.apiBase.getProcessFormFieldInfo(Long.parseLong(defKey), Integer.parseInt(ver));
                Map<String,List<Map>> childTableFieldInfo = objFormUtils.getObjectChildFormFieldInfo(Long.parseLong(defKey), Integer.parseInt(ver));
                logger.debug("Parent");
                logger.debug("" + fieldInfo);
                logger.debug("Children");
                logger.debug("" + childTableFieldInfo);
                return;
            }
        }
        catch(Exception e)
        {
            logger.error("APIError",e);
        }
    }

    public String setNextGroupApprover(String resourceName,String objectInstanceKey)
    {
        tcFormInstanceOperationsIntf formInstOps = null;
        tcFormDefinitionOperationsIntf formDefOps = null;
        tcObjectOperationsIntf objectOp = null;
        
        tcResultSet rs = null;
        
        try
        {
            formInstOps = (tcFormInstanceOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormInstanceOperationsIntf.class);
            formDefOps = (tcFormDefinitionOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormDefinitionOperationsIntf.class);
            objectOp = (tcObjectOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcObjectOperationsIntf.class);
            //rs = formInstOps.getObjectFormData(Long.parseLong(objectInstanceKey));
            
            String childName = getChildFormNameForResource(resourceName);
            OIMObjectFormUtilities formUtils = OIMUtilityGetter.getObjectFormUtilities(logger, objectOp,formInstOps, formDefOps);
            
            Map reqObj = formUtils.getObjectFormValues(Long.parseLong(objectInstanceKey), true, null);
            
            logger.debug("Object Form Data for " + resourceName);
            Set<String> keys = reqObj.keySet();
            Iterator<String> i = keys.iterator();
            String GROUPAPPROVALKEY = null;
            while(i.hasNext())
            {
                String k = i.next();
                String v = (String)reqObj.get(k);
                if (k.contains("GROUPAPPROVALKEY"))
                    GROUPAPPROVALKEY = k;
                    
                logger.debug(k + ":" + v);
            }
            
            Map[] reqChildren = formUtils.getObjectFormChildValues(Long.parseLong(objectInstanceKey), childName, true, null);
            String nextGroupToApprove = null;
                    
            for(int c=0;c<reqChildren.length;c++)
            {
                Map childObj = reqChildren[c];
                Set<String> ckeys = childObj.keySet();
                Iterator<String> ci = ckeys.iterator();
                while(ci.hasNext())
                {
                    String k = ci.next();
                    String v = (String)childObj.get(k);
                    if (k.contains("LASTAPPROVER_ID"))
                    {
                        String lastId = v;
                        if (lastId == null || lastId.trim().length() == 0)
                        {
                            nextGroupToApprove = (String)childObj.get(childName + "_KEY");
                            break;
                        }
                    }
                    
                    logger.debug(k + ":" + v);
                }
                
                if (nextGroupToApprove != null && GROUPAPPROVALKEY != null)
                {
                    Map tmpMap = new HashMap();
                    tmpMap.put(GROUPAPPROVALKEY,nextGroupToApprove);
                    logger.debug("Setting Next Group Key " + tmpMap);
                    formUtils.setObjectFormValues(Long.parseLong(objectInstanceKey), tmpMap);
                    return "ASSIGNAPPROVER";

                }
                
            }
            
            return "SUCCESS";
        }
        catch(Exception e)
        {
            logger.error("Error setNextGroupApproval",e);
        }
        return "FAILURE";
        
        
    }
    
    private String getChildFormNameForResource(String resourceName)
    {
        try
        {
            String childName = apiBase.getLookupValue(resourceName, "Lookup.BofA.Resource.ChildObjectForms");
            return childName;
        }
        catch(Exception e)
        {
            logger.error("Error getChildFormNameForResource",e);
        }
        return null;
    }
    
    

}
